package jwt

import (
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/golang-jwt/jwt/v5"
	"github.com/google/uuid"
	"github.com/redis/go-redis/v9"
	"net/http"
	"strings"
	"time"
)

var (
	Access_token=[]byte("qJfZR1psrw3PXpT1aPbeRoUl0eLtdBH2bcFobbf9MKhdbd8MoR2V046H0obQd2tc")
	Refresh_token=[]byte("qJfZR1psrw22XpTsdafsdrdsfdsafsdH2bcFobbf9MKhdbd8MoR2V046H0obQ2tc")
)

type RedisJWTHandler struct {
	cmd redis.Cmdable
}


func NewRedisJWTHandler(cmd redis.Cmdable) Handler{
	return &RedisJWTHandler{
		cmd: cmd,
	}
}

func (h *RedisJWTHandler) ExtractToken(ctx *gin.Context) string {
	tokenHeader := ctx.GetHeader("Authorization")
	if tokenHeader == "" {
		// 没登陆
		ctx.AbortWithStatus(http.StatusUnauthorized)
		return ""
	}
	//segs := strings.SplitN(tokenHeader, " ",2)
	segs := strings.Split(tokenHeader, " ")
	if len(segs) != 2 {
		ctx.AbortWithStatus(http.StatusUnauthorized)
		return ""
	}
	return segs[1]
}

func (h *RedisJWTHandler) ClearToken(ctx *gin.Context) error {
	ctx.Header("x-jwt-token","")
	ctx.Header("x-refresh-token","")
	c,_:=ctx.Get("claims")
	claims, ok:=c.(UserClaims)
	if !ok {
		ctx.String(http.StatusOK,"系统错误")
		return errors.New("系统错误")
	}
	err:=h.cmd.Set(ctx, fmt.Sprintf("users:ssid:%s", claims.Ssid),"",time.Hour*24*7).Err()
	if err!=nil{
		return err
	}
	ctx.JSON(200,"退出登录成功")
	return nil
}

func (h *RedisJWTHandler) CheckSession(ctx *gin.Context, ssid string) error {
	cnt, err:=h.cmd.Exists(ctx,fmt.Sprintf("users:ssid:%s", ssid)).Result()
	if err!=nil || cnt>0{
		// redis有问题或者已经退出
		ctx.AbortWithStatus(http.StatusUnauthorized)
		return err
	}
	return nil
}



func (h *RedisJWTHandler) SetLoginToken(ctx *gin.Context, uid int64) error {
	ssid:=uuid.New().String()
	err:=h.SetJWTToken(ctx, uid, ssid)
	if err!=nil {
		return err
	}

	err = h.SetRefreshToken(ctx, uid, ssid)
	if err!=nil {
		return err
	}
	return nil
}

func (h *RedisJWTHandler) SetJWTToken(ctx *gin.Context, uid int64, ssid string) error {
	claims := UserClaims{
		RegisteredClaims: jwt.RegisteredClaims{
			ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Minute*10)),
		},
		Ssid:      ssid,
		Uid:       uid,
		UserAgent: ctx.Request.UserAgent(),
	}
	token := jwt.NewWithClaims(jwt.SigningMethodHS512, claims)
	//fmt.Println("token: ", token)
	tokenStr, err := token.SignedString(Access_token)
	//fmt.Println("tokenStr: ", tokenStr)
	if err != nil {
		return err
	}

	// 返回给前端
	ctx.Header("x-jwt-token", tokenStr)
	return nil
}

func (h *RedisJWTHandler) SetRefreshToken(ctx *gin.Context, uid int64, ssid string) error {
	claims := UserClaims{
		RegisteredClaims: jwt.RegisteredClaims{
			ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour*24*7)),
		},
		Ssid: ssid,
		Uid:       uid,
		UserAgent: ctx.Request.UserAgent(),
	}
	token := jwt.NewWithClaims(jwt.SigningMethodHS512, claims)
	tokenStr, err := token.SignedString(Refresh_token)
	if err != nil {
		return err
	}
	//fmt.Println("token: ", token)
	//fmt.Println("tokenStr: ", tokenStr)
	// 返回给前端
	ctx.Header("x-refresh-token", tokenStr)
	return nil
}


